﻿using TrueSync;


namespace HEFramework
{
    public static class AISkillComponentSystem
    {
        [EntitySystem]
        public class AISkillComponentAwakeSystem : AwakeSystem<AISkillComponent>
        {
            protected override void Awake(AISkillComponent _self)
            {
            }
        }

        [EntitySystem]
        public class AISkillComponentUpdateSystem : UpdateSystem<AISkillComponent>
        {
            protected override void Update(AISkillComponent _self)
            {
                var dc = _self.GetSceneChild<DataTableComponent>();
                if (dc == null)
                {
                    return;
                }

                var main = _self.GetMainEntity();
                var sc = main.GetChild<SkillComponent>();
                var alc = main.GetChild<AlertComponent>();
                if (sc == null || alc == null)
                {
                    return;
                }

                //附近有敌方才开启技能释放
                if (!alc.IsAlert())
                {
                    return;
                }

                Entity entity = null;
                var table = dc.LoadDataTable<DRAISkill>();
                for (int i = 0; i < sc.SkillIDs.Count; i++)
                {
                    int id = sc.SkillIDs[i];
                    var data = table.GetData(id);
                    if (data == null)
                    {
                        continue;
                    }

                    switch (data.Type)
                    {
                        case (int)eAISkillType.None:
                            continue;
                        case (int)eAISkillType.Self:
                            entity = main;
                            break;
                        case (int)eAISkillType.Alert:
                            entity = alc.Target;
                            break;
                        case (int)eAISkillType.Condition:
                            entity = _self.ConditionTarget(data.ID);
                            break;
                    }

                    if (entity == null)
                    {
                        continue;
                    }

                    //触发技能
                    sc.TriggerActiveSkill(id, entity);
                }
            }
        }

        private static Entity ConditionTarget(this AISkillComponent _self, int _id)
        {
            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return null;
            }

            var main = _self.GetMainEntity();
            var alc = main.GetChild<AlertComponent>();
            var acA = main.GetChild<AttributeComponent>();
            var tcA = main.GetChild<TransformComponent>();
            if (alc == null || acA == null || tcA == null)
            {
                return null;
            }

            //目标类型过滤
            var data = dc.LoadDataTable<DRAISkill>().GetData(_id);
            using ListObject<EntityRef<Entity>> entities = ListObject<EntityRef<Entity>>.Create();
            switch (data.ConditionAType)
            {
                case (int)eAISkillConditionAType.Self:
                    entities.Add(main);
                    break;
                case (int)eAISkillConditionAType.Team:
                    entities.AddRange(alc.Teams);
                    break;
                case (int)eAISkillConditionAType.Friend:
                    entities.AddRange(alc.Friends);
                    break;
                case (int)eAISkillConditionAType.Enemy:
                    entities.AddRange(alc.Enemies);
                    break;
                case (int)eAISkillConditionAType.TeamNoSelf:
                    entities.AddRange(alc.Teams);
                    entities.Remove(_self.GetMainEntity());
                    break;
            }


            //属性类型过滤
            int attributeType = 0;
            switch (data.ConditionBType)
            {
                case (int)eAISkillConditionBType.Normal:
                    attributeType = (int)eAttributeType.Normal;
                    break;
                case (int)eAISkillConditionBType.Hero:
                    attributeType = (int)eAttributeType.Hero;
                    break;
                case (int)eAISkillConditionBType.Build:
                    attributeType = (int)eAttributeType.Build;
                    break;
            }

            for (int i = entities.Count - 1; i >= 0; i--)
            {
                var entity = entities[i].Entity;
                var ac = entity.GetChild<AttributeComponent>();
                if (ac.Attribute.Type != attributeType)
                {
                    entities.Remove(entity);
                }
            }


            //数值类型过滤
            Entity target = null;
            FP valueMin = FP.MaxValue;
            FP valueMax = 0;
            FP value = 0;
            for (int i = 0; i < entities.Count; i++)
            {
                var entity = entities[i].Entity;
                var acB = entity.GetChild<AttributeComponent>();
                var tcB = entity.GetChild<TransformComponent>();

                if (acB == null || tcB == null)
                {
                    continue;
                }

                switch (data.ConditionCType)
                {
                    case (int)eAISkillConditionCType.Distance:
                        value = TSVector.Distance(tcA.P, tcB.P) * 1000;
                        break;
                    case (int)eAISkillConditionCType.HP:
                        value = acB.HP;
                        break;
                    case (int)eAISkillConditionCType.MP:
                        value = acB.MP;
                        break;
                    case (int)eAISkillConditionCType.P_ATK:
                        value = acB.P_ATK.Value;
                        break;
                    case (int)eAISkillConditionCType.M_ATK:
                        value = acB.M_ATK.Value;
                        break;
                    case (int)eAISkillConditionCType.HP_PCT:
                        value = acB.HP / acB.X_HP.Value;
                        break;
                    case (int)eAISkillConditionCType.MP_PCT:
                        value = acB.MP / acB.X_MP.Value;
                        break;
                }


                switch (data.ConditionDType)
                {
                    case (int)eAISkillConditionDType.Min:
                        if (value < valueMin)
                        {
                            target = entity;
                            valueMin = value;
                        }

                        break;
                    case (int)eAISkillConditionDType.Max:
                        if (value > valueMax)
                        {
                            target = entity;
                            valueMax = value;
                        }

                        break;
                }
            }

            return target;
        }

        private static Entity GetMainEntity(this AISkillComponent _self)
        {
            return _self.Parent;
        }
    }
}